在寫原生 JavaScript 時,我們常常會用 document.querySelector
來獲取 DOM 元素,在 React 你可以使用 useRef 直接在元素上做綁定,已達到指定 DOM 的行為動作。除了訪問 DOM,useRef 還可以用來儲存資料、抓取以前的值。
useRef 會自己建立一個 mutable ref object
,裡面會有一個 current
屬性設為相應的 DOM 節點或資料,不會隨著元件 re-render 被重新創造,所以 useRef 每次都會返回同一個 ref object
Mutable object
:以傳址(by reference)方式被儲存,物件被創造後,參考固定,但參考的記憶體內容可以改變,如 JavaScript 的參考型別 Object、Array、Function 等
Immutable object
:以傳值(by value)方式被儲存,物件被創造後,其 value 無法被改變,如 JavaScript 的原始型別 number、string、null、undefined、boolean 等
import { useRef } from "react";
const refContainer = useRef(initialValue);
refContainer 為自定義變數
initialValue 為初始值,可以為任何值
refContainer.current
從 .current
取得 ref object 的值,實際操作會在使用情境做說明
import { useEffect, useRef } from "react";
const App = () => {
const myInput = useRef();
useEffect(() => {
myInput.current.focus();
}, []);
return (
<div>
<label>Name:</label>
<input type="text" ref={myInput} />
</div>
);
};
export default App;
情境說明:
操作說明:
<input type="text" />
,並在 useEffect 操作 .focus 動作更新 useRef 是 side Effect 的行為,因此要在 useEffect 或 event handler 裡執行
打開 codesandbox 程式碼範例 看看吧!
import { useRef, useEffect, useState } from "react";
const App = () => {
const [name, setName] = useState("");
const renderCount = useRef(1);
useEffect(() => {
renderCount.current += 1;
});
return (
<>
<input
type="text"
value={name}
onChange={(e) => {
setName(e.target.value);
}}
/>
<p>I rendered {renderCount.current} times!</p>;
</>
);
};
export default App;
情境說明:
操作說明:
renderCount.current += 1
打開 codesandbox 程式碼範例 看看吧!
import { useState, useRef, useEffect } from "react";
const App = () => {
const [name, setName] = useState("");
const previousName = useRef(name);
useEffect(() => {
previousName.current = name;
console.log(previousName.current);
}, [name]);
return (
<div>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<p>
My name is <span>{name}</span>
</p>
<p>
My previous name is
<span>{previousName.current}</span>
</p>
</div>
);
};
export default App;
情境說明:
操作說明:
previousName.current = name
ref 與 state 的差異就是 ref 更新不會觸發 re-render,state 才會,所以即使 ref 已更新成輸入後的 name,畫面也不會隨著渲染,會在下一次 useState re-render 後出現
打開 condsandbox 程式碼範例 看看吧!
之前比較常看到 useRef 用來操作 dom,原來也可以定義不會導致畫面重新渲染的資料,理解了 ref 跟 state 的使用上是差在 ref 不會觸發 re-render,今天到這邊結束,明天再繼續吧!!
Learn useRef in 11 Minutes
一個範例讓你搞懂useState, useRef, useEffect | 5分鐘快速教學
本文將同步更新至我的部落格
Lala 的前端大補帖